import { Injectable, Logger, OnModuleInit } from "@nestjs/common";
import { spawn } from "child_process";
import * as path from "node:path";
import { Observable, Observer } from "rxjs";
import * as process from "node:process";
import { breathConfig } from "../../../config";
import * as os from "node:os";

const fs = require("fs-extra");

enum ENV {
  exe = "exe",
  dev = "dev",
  prod = "prod",
  docker_prod = "docker_prod",
}

@Injectable()
export class CallFilterService implements OnModuleInit {
  pyProcess;
  oberserveFilterData;
  tempDir;
  private readonly logger = new Logger(CallFilterService.name);

  constructor() {}

  onModuleInit() {
    this.start();
  }

  start(pyPath = "") {
    try {
      this.setupPythonExe(pyPath);
    } catch (error) {
      console.log(error);
    }
  }

  stop() {
    this.pyProcess.kill("SIGTERM");
  }

  sendMsg(data) {
    // console.log(`发送${data.low},${data.hi},${data.order},${data.yCenter}`);
    const msg = JSON.stringify(data);
    this.pyProcess.stdin.write(msg + "\n");
  }

  waitMsg() {
    return new Observable((observer: Observer<any>) => {
      this.oberserveFilterData = observer;
    });
  }

  setupPythonExe(pyPath = "") {
    const env = this.getRunEnv();
    let exePath = "";
    console.log(`getRunEnv: `, env);
    if (env === ENV.docker_prod) {
      // this.pyProcess = spawn('python', ['main.py'], {
      //   cwd: '/app',  // 确保这是 Python 脚本在容器中的正确路径
      // });
      // 以命令行形式运行。
      this.pyProcess = spawn("docker-compose", [
        "exec",
        "-T",
        "breath-data-process",
        "python",
        "main.py",
      ]);
    } else {
      if (env === ENV.exe) {
        const pkgExePath = path.join(__dirname, "filter.exe");
        this.tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "filter-"));
        console.log('pkgExePath',pkgExePath,'tmpDir', this.tempDir);
        exePath = path.join(this.tempDir, "filter.exe");
        // 将 filter.exe 复制到临时目录
        try {
          console.log("将文件路径拷贝到临时路径")
          fs.copyFileSync(pkgExePath, exePath);
        }catch (e) {
          console.log(`将pkg文件复制到临时路径出错，`,e.message);
        }
        console.log("pkg 环境", exePath);
      } else if (env === ENV.dev) {
        exePath = path.resolve(
          "./apps/breath-server/src/filter/",
          `${breathConfig.filterExeName}.exe`,
        );
        console.log("dev环境", exePath);
      } else if (env === ENV.prod) {
        // 在开发环境中，__dirname 是源代码的实际路径,这个if只在单元测试中使用。
        if (pyPath !== "") {
          exePath = pyPath;
        } else {
          exePath = path.resolve(
            __dirname,
            `./${breathConfig.filterExeName}.exe`,
          );
        }
        console.log("build后node环境", exePath);
      }
      this.pyProcess = spawn(exePath);
    }

    this.logger.log("py filter process setup");
    let resultBuffer = "";
    this.pyProcess.stdout.on("data", (data) => {
      resultBuffer += data.toString();
      // console.log(resultBuffer);
      const lines = resultBuffer.split("\n");
      const ans: string = lines[0];
      if (ans.length <= 100) {
        console.log("收到消息长度少于100");
        console.error(ans);
        resultBuffer = "";
      } else if (!ans.startsWith("setup")) {
        try {
          const jsonAns = JSON.parse(ans);
          this.oberserveFilterData.next(jsonAns);
        } catch (ex) {
          console.error(ex);
        }
      }
      resultBuffer = "";
    });
    this.pyProcess.on("error", (err) => {
      if (this.tempDir) {
        fs.removeSync(this.tempDir);
        this.tempDir = "";
      }
      console.log("py error", err);
    });

    this.pyProcess.on("close", (code) => {
      fs.removeSync(this.tempDir);
      this.tempDir = "";
      if (code === 0) {
        console.log("filter.exe process exited successfully");
      } else {
        console.error(`main.exe process exited with code ${code}`);
        // 可以根据需要处理非正常退出的情况
      }
    });
  }

  getRunEnv() {
    let env = "";
    if ((process as any).pkg) {
      env = ENV.exe;
    } else if ((process as any).env.NODE_ENV === "development") {
      env = ENV.dev;
    } else if ((process as any).env.NODE_ENV === "docker-production") {
      env = ENV.docker_prod;
    } else {
      env = ENV.prod;
    }
    return env;
  }
}
